#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;
const int maxn = 1 << 10;
vector<int> nums; // 存放符合条件的平方数的数字状态
int ans;

//关于状态标记的说明 ：0100101101 从左往右 9876543210

void check(long long x)
{
    int status = 0;// 初始状态全部标记为0
    if(x == 0) status = 1;// 标记最低位为1
    while(x)
    {
        //获取10进制个位上的数，1移位后与上一次的状态做与运算
        //不为0说明个位上的数字已经被使用，则不记录 return
        if((status & (1 << (x%10)))!=0) return;
        //记录数字使用情况
        status |= (1 <<(x%10)); //标记个位对应的数字为1
        x /= 10; //消掉个位
        //继续处理 
    }
    //此时，原始的x的每一位都被标记到了status中，且没有重复的数字
    nums.push_back(status);  //将这个状态添加到nums集合中，以便组和使用
}

void dfs(int x, int y)   //从第x个合法数字往后取，当前的组和状态为y
{
    if(y == (1 << 10)-1)  //组和可行记录答案
    {
        ans++;
        return;
    }
    for(int i=x; i<nums.size();i++)
    {
        //枚举新加入数字的状态
        if((nums[i] & y)==0) //可以加入组和
        {
            dfs(i+1, nums[i]|y);  //继续寻找下一个数字
        }
    }

    
}


int main()
{
    //枚举算出满足题意的平方数并存储其状态
    for(long long i=0;i<=100000;i++)
    {
        check(i*i);   //形成小于9876543210的所有平方数
    }
    //用深度搜索顺序组和预处理出的平方数
    dfs(0,0);  //初始从第0个位置向后取，初始组和状态为0
    cout << ans << endl;
    return 0;   
}